<template>
  <a-modal
    :title="title"
    :width="1000"
    :visible="visible"
    :maskClosable="false"
    :confirmLoading="confirmLoading"
    @cancel="handleCancel"
  >
    <a-spin :spinning="confirmLoading">
      <a-back-top :target="backTop"/>
      <div v-show="parameterShow">
        <a-form :form="form">
          <a-form-item
            :labelCol="labelCol"
            :wrapperCol="wrapperCol"
            v-for="(parameter, index) in parameters"
            :label="parameter.name"
            :key="parameter.name + index"
          >
            <a-input
              v-model="parameter.value"
              v-if="
                                parameter.type === 'str' &&
                                !scriptDetail.group_name.match(/.推送版本包/gi) &&
                                !scriptDetail.group_name.match(/.后台更新/gi)
                            "
            ></a-input>

            <a-select
              show-search
              allow-clear
              mode="combobox"
              v-model="parameter.value"
              placeholder="选择版本..."
              @focus="fetchVersion"
              v-if="
                                parameter.type === 'str' &&
                                (scriptDetail.group_name.match(/.推送版本包/gi) || scriptDetail.group_name.match(/.后台更新/gi))
                            "
            >
              <a-select-option v-for="item in versionList" :key="item">
                {{ item }}
              </a-select-option>
            </a-select>

            <a-select
              allow-clear
              placeholder="请选择....."
              v-model="parameter.value"
              v-if="parameter.type === 'option'"
            >
              <a-select-option v-for="item in parameter.option" :key="item" :value="item"
              >{{ item }}
              </a-select-option>
            </a-select>
            <span class="ant-descriptions-item-content">
              <pre style="display: flex">{{ parameter.desc }}</pre>
            </span>
          </a-form-item>
        </a-form>
      </div>

      <div v-show="execShow">
        <a-steps :current="current" :status="status">
          <a-step title="连接主机"></a-step>
          <a-step title="任务执行">
            <a-icon slot="icon" type="loading" v-if="status === 'process'"/>
          </a-step>
          <a-step title="执行完成"></a-step>
        </a-steps>
        <div class="steps-content">
          <div v-if="scriptDetail.log_command">
            <pre class="output" v-html="backlog"></pre>
          </div>
          <div v-else>
            <p class="output" v-for="(item, index) in nowLog" :key="index">{{ item }}</p>
          </div>
          <a-icon type="loading" v-if="deployDom.icon"/>
        </div>
      </div>
    </a-spin>

    <template slot="footer">
      <div v-show="execBtnShow">
        <a-button key="submit" type="primary" :disabled="deployDom.clickTrue" @click="handleSubmit">
          执行
        </a-button>
      </div>
    </template>
  </a-modal>
</template>
<script>
  import { XCard } from '@/components'
  import { toExecute, getScriptLog, getGameVersion, getScriptExecLog } from '@/api/main/script'
  import { mapGetters } from 'vuex'

  export default {
    name: 'execForm',
    components: {
      XCard
    },
    data() {
      return {
        labelCol: {
          xs: { span: 10 },
          sm: { span: 5 }
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 15 }
        },
        visible: false,
        title: '构建控制台',
        activeKey: ['1'],
        confirmLoading: true,
        parameterShow: true,
        execBtnShow: true,
        execShow: false,
        logBtnShow: false,
        logShow: false,
        parameters: [],
        versionList: [],
        form: this.$form.createForm(this),
        nowLog: [],
        scriptDetail: {},
        deployDom: {
          icon: false,
          clickTrue: false
        },
        nowKey: '',
        outputs: {},
        backlog: '',
        status: 'wait',
        current: 0,
        timer: null
      }
    },
    computed: {
      ...mapGetters(['token', 'nickname', 'username'])
    },
    watch: {
      nowLog() {
        this.$nextTick(() => {
          var container = document.querySelector('.ant-modal-wrap')
          container.scrollTop = container.scrollHeight + 150
        })
      }
    },
    methods: {
      // 初始化方法
      open(record) {
        this.visible = true
        this.parameters = record.parameters
        this.scriptDetail = record
        this.deployDom.clickTrue = false
        if (record.build_token) {
          // this.getScriptExecLog(record.build_token, record.id, record.build_id)
          this.getScriptLog(record.id, record.build_id)
          this.initWebSocket(record.build_token)
          this.parameterShow = false
          this.execShow = true
        } else {
          if (record.task) {
            this.getScriptLog(record.task, record.build_id)
            this.execShow = true
            this.execBtnShow = false
          }
          this.parameterShow = true
        }
        // if (record.log_command) {
        //   this.timer = window.setInterval(() => {
        //     setTimeout(this.getScriptExecLog(record.id), 0)
        //   }, 5000)
        // }

        this.confirmLoading = false
      },
      backTop() {
        return document.querySelector('.ant-modal-wrap')
      },
      fetchVersion() {
        let params = {
          project: this.scriptDetail.project,
          language: this.scriptDetail.language
        }
        getGameVersion(params).then((res) => {
          this.versionList = []
          if (this.scriptDetail.group_name.match(/.后台更新/gi)) {
            for (const version of res.data) {
              const tmp = version.replace('.zip', '')
              this.versionList.push(tmp)
            }
            return
          }
          this.versionList = res.data
        })
      },
      // 渲染服务端消息
      _parse_message(message) {
        const { key, step, status, data } = message
        if (step) {
          this.current = step
          // console.log(this.current, "0000")
        }
        if (this.outputs[key]) {
          if (data !== undefined) this.outputs[key]['data'].push(data)
        } else {
          this.outputs[key] = {}
          this.outputs[key]['data'] = []
          this.outputs[key]['status'] = ''
          if (data !== undefined) this.outputs[key]['data'].push(data)
        }
        if (status !== undefined) {
          // 更改当前记录的状态
          this.outputs[key]['status'] = status
          if (this.outputs[key]['status'] === 'info') {
            this.status = 'process'
            this.deployDom.icon = true
            this.deployDom.clickTrue = true
          } else if (this.outputs[key]['status'] === 'success') {
            this.status = 'finish'
            this.deployDom.icon = false
          } else if (this.outputs[key]['status'] === 'error') {
            this.status = 'error'
            this.deployDom.icon = false
          }
        }
        this.nowLog = this.outputs[this.nowKey].data
      },
      // 获取日志数据
      getScriptLog(id, rid) {
        const params = { id: id, rid: rid }
        getScriptLog(params).then((res) => {
          this.nowKey = id + '_' + rid
          const msg = res.data
          for (let mi = msg.length - 1; mi >= 0; mi--) {
            this._parse_message(JSON.parse(msg[mi]))
          }
        })
      },
      // 获取正在执行日志
      getScriptExecLog(id) {
        getScriptExecLog({ id: id }).then((res) => {
          this.backlog = res.data.replace(/\n/g, '<br>')
        })
      },
      // 开始执行
      handleSubmit() {
        this.confirmLoading = true
        this.execShow = true
        this.parameterShow = false
        this.confirmLoading = false
        const env = {}
        for (const item of this.parameters) {
          env[item.name] = item.value
        }
        if (this.scriptDetail.group_name.match(/.测试服更新/gi)) {
          env['name'] = this.nickname + '(' + this.username + ')'
        }
        if (this.scriptDetail.group_name.match(/.后台更新/gi)) {
          env['Ouser'] = this.username
        }
        const params = { id: this.scriptDetail.id, env: env }
        toExecute(params).then((res) => {
          if (res.data.token) {
            this.nowKey = this.scriptDetail.id + '_' + res.data.build_id
            this.initWebSocket(res.data.token)
          }
        })
      },
      // 获取websocket连接地址
      getWsUrl(token) {
        const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
        const urlFamily = window.location.host.split(':')
        const hostname = urlFamily[0]
        let urlPort = urlFamily.length === 2 ? Number(urlFamily[1]) : null
        if (urlPort === 81) {
          urlPort = 9001
        }
        return `${protocol}//${hostname}${urlPort ? ':' + urlPort : ''}${urlPort !== 9001 ? '/api' : ''}/ws/exec/${token}/?x-token=${this.token}`
      },
      initWebSocket(token) {
        this.socket = new WebSocket(this.getWsUrl(token))

        this.socket.onmessage = (e) => {
          if (e.data === 'pong') {
            // this.socket.close();
            this.socket.send('ping')
          } else {
            this._parse_message(JSON.parse(e.data))
          }
        }
        this.socket.onopen = () => {
          this.socket.send('ok')
        }
      },
      // [取消按钮]重置数据,关闭弹框
      handleCancel() {
        this.nowLog = []
        this.outputs = {}
        this.execShow = false
        this.logBtnShow = false
        this.backlog = ''
        this.parameters = []
        this.visible = false
        window.clearInterval(this.timer)
        this.timer = null
        if (this.socket) {
          this.socket.close()
        }
      }
    }
  }
</script>

<style scoped>
  .steps-content {
    margin-top: 24px;
    min-height: 40px;
    padding: 10px 15px;
    border: 1px solid #d9d9d9;
    border-radius: 4px;
    background-color: #fafafa;
  }

  .output {
    margin: 0;
    font-size: 1em;
    font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
  }
</style>
